package org.alwayssuper.protocol.gbt32960;

import org.alwayssuper.protostar.annotation.Field;
import org.alwayssuper.protostar.annotation.Message;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.alwayssuper.protocol.basics.GBTMessage;
import org.alwayssuper.protocol.commons.GBTRequestType;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * G01 车辆登入消息
 * 支持GB/T 32960.3-2016 (version=0) 和 GB/T 32960.3-2025 (version=1) 两个版本
 * 
 * 版本差异:
 * - 2016版: 使用可充电储能子系统相关字段
 * - 2025版: 使用电池管理系统和动力蓄电池包相关字段
 * 
 * 基于T8602模式重构，每个内部类自己管理长度信息
 * 
 * @author alwaysSuper
 */
@ToString
@Data
@Accessors(chain = true)
@Message(GBTRequestType.车辆登入)
public class G01 extends GBTMessage {

    // 通用字段 - 两个版本共用
    @Field(length = 6, desc = "数据采集时间(YYMMDDHHMMSS)", version = {0, 1})
    private LocalDateTime collectTime;
    
    @Field(length = 2, desc = "登入流水号:车载终端每登入一次,登入流水号自动加1,从1开始循环累加,最大值为65531,循环周期为天", version = {0, 1})
    private int loginSeqNo;
    
    @Field(length = 20, charset = "ASCII", desc = "ICCID:SIM卡ICCID号(ICCID应为终端从SIM卡获取的值,不应人为填写或修改)", version = {0, 1})
    private String iccId;

    // 2016版本充电系统格式
    @Field(length = 1,  version = 0, desc = "V2016:可充电储能子系统数:可充电储能子系统数n,有效值范围:0~250")
    private int subsysCount;

    @Field(length = 1, version = 0, desc = "可充电储能系统编码长度:可充电储能系统编码长度m,有效范围:0~50,0表示不上传该编码")
    private int subsysCodeLen;

    @Field(version = 0,desc = "可充电储能系统编码列表:可充电储能系统编码宜为终端从车辆获取的值")
    private String subsysCodes;

    // 2025版本充电系统格式
    //电池管理系统数:电池管理系统数n,有效值范围:0~20(由bmsPackCounts中的lengthUnit获取)
    private int bmsCount;

    @Field(totalUnit = 1, version = 1, desc = "电池管理系统对应动力蓄电池包个数:电池管理系统对应动力蓄电池包个数m,有效范围:0~50")
    private List<BmsPackCountEntry> bmsPackCounts;

    @Field(version = 1, desc = "动力蓄电池包编码:动力蓄电池包编码按GB/T34014标准,24字节编码")
    private List<BatteryPackEncoding> batteryPackEncodings;

    // BMS电池包个数条目类
    @ToString
    @Data
    @Accessors(chain = true)
    public static class BmsPackCountEntry {
        @Field(length = 1, desc = "该电池管理系统对应动力蓄电池包个数，有效范围:0~50")
        private int batteryPackCount;
    }

    // 动力蓄电池包编码类
    @ToString
    @Data
    @Accessors(chain = true)
    public static class BatteryPackEncoding {
        @Field(length = 24, charset = "ASCII", desc = "动力蓄电池包编码:24字节编码,按GB/T34014标准")
        private String batteryPackCode;
    }

    // 通过bmsPackCounts列表长度返回bmsCount
    public int getBmsCount() {
        return bmsPackCounts == null ? 0 : bmsPackCounts.size();
    }

    /**
     * 获取2016版本可充电储能系统编码列表的准确个体值
     * @return 可充电储能系统编码数组，如果为null或空返回空数组
     */
    public String[] getSubsysCodesArray() {
        if (subsysCodes == null || subsysCodes.isEmpty() || subsysCodeLen == 0) {
            return new String[0];
        }
        
        // 按照编码长度分割字符串
        String[] codes = new String[subsysCount];
        for (int i = 0; i < subsysCount && i * subsysCodeLen < subsysCodes.length(); i++) {
            int start = i * subsysCodeLen;
            int end = Math.min(start + subsysCodeLen, subsysCodes.length());
            codes[i] = subsysCodes.substring(start, end).trim();
        }
        return codes;
    }

    /**
     * 设置2016版本可充电储能系统编码列表
     * @param codes 编码数组
     */
    public void setSubsysCodesArray(String[] codes) {
        if (codes == null || codes.length == 0) {
            this.subsysCount = 0;
            this.subsysCodeLen = 0;
            this.subsysCodes = "";
            return;
        }
        
        this.subsysCount = codes.length;
        // 计算最大编码长度
        int maxLen = 0;
        for (String code : codes) {
            if (code != null && code.length() > maxLen) {
                maxLen = code.length();
            }
        }
        this.subsysCodeLen = maxLen;
        
        // 拼接所有编码，不足长度的用空格补齐
        StringBuilder sb = new StringBuilder();
        for (String code : codes) {
            if (code == null) code = "";
            sb.append(String.format("%-" + subsysCodeLen + "s", code));
        }
        this.subsysCodes = sb.toString();
    }

    /**
     * 获取2025版本动力蓄电池包编码列表的准确个体值
     * @return 动力蓄电池包编码数组，如果为null或空返回空数组
     */
    public String[] getBatteryPackEncodingsArray() {
        if (batteryPackEncodings == null || batteryPackEncodings.isEmpty()) {
            return new String[0];
        }
        
        return batteryPackEncodings.stream()
                .map(BatteryPackEncoding::getBatteryPackCode)
                .filter(code -> code != null && !code.trim().isEmpty())
                .toArray(String[]::new);
    }

    /**
     * 设置2025版本动力蓄电池包编码列表
     * @param codes 编码数组
     */
    public void setBatteryPackEncodingsArray(String[] codes) {
        if (codes == null || codes.length == 0) {
            this.batteryPackEncodings = new ArrayList<>();
            return;
        }
        
        this.batteryPackEncodings = new ArrayList<>();
        for (String code : codes) {
            if (code != null && !code.trim().isEmpty()) {
                BatteryPackEncoding encoding = new BatteryPackEncoding();
                encoding.setBatteryPackCode(code.trim());
                this.batteryPackEncodings.add(encoding);
            }
        }
    }

    /**
     * 获取2025版本BMS对应的动力蓄电池包个数数组
     * @return BMS对应的动力蓄电池包个数数组，如果为null或空返回空数组
     */
    public int[] getBmsPackCountsArray() {
        if (bmsPackCounts == null || bmsPackCounts.isEmpty()) {
            return new int[0];
        }
        
        return bmsPackCounts.stream()
                .mapToInt(BmsPackCountEntry::getBatteryPackCount)
                .toArray();
    }

    /**
     * 设置2025版本BMS对应的动力蓄电池包个数数组
     * @param counts BMS对应的动力蓄电池包个数数组
     */
    public void setBmsPackCountsArray(int[] counts) {
        if (counts == null || counts.length == 0) {
            this.bmsPackCounts = new ArrayList<>();
            return;
        }
        
        this.bmsPackCounts = new ArrayList<>();
        for (int count : counts) {
            if (count >= 0) {
                BmsPackCountEntry entry = new BmsPackCountEntry();
                entry.setBatteryPackCount(count);
                this.bmsPackCounts.add(entry);
            }
        }
    }

    @Override
    public int getSerialNo() {
        return loginSeqNo;
    }

}
